import { PlusOutlined } from '@ant-design/icons'
import { Modal, Upload, message } from 'antd'
import { useEffect, useState, useCallback } from 'react'
import {
  FormattedMessage,
  getPlatformToken,
  getTenantToken,
} from '@designable/event-system'
import React from 'react'
import type { UploadFile } from 'antd'

// 上传响应接口
interface UploadResponse {
  code: number
  msg: string
  data: {
    fileUrl: string
  }
}

// 文件项接口
interface FileItem extends UploadFile {
  url?: string
  response?: UploadResponse
}

// 组件Props接口
interface UploadImageProps {
  apiName?: 'platform' | 'tenant'
  maxSize?: number // 文件大小限制，单位MB
  accept?: string // 接受的文件类型
  maxCount?: number // 最大上传数量
  value?: string[] | string
  onChange?: (url: string[] | string) => void
}

export const UploadImage: React.FC<UploadImageProps> = (props) => {
  const {
    value,
    onChange,
    apiName = 'tenant',
    maxSize = 10, // 默认5MB
    accept = '.jpg,.jpeg,.png,.gif',
    maxCount = 1,
  } = props

  const [previewVisible, setPreviewVisible] = useState(false)
  const [previewImage, setPreviewImage] = useState('')
  const [fileList, setFileList] = useState<FileItem[]>([])

  useEffect(() => {
    if (!value || (Array.isArray(value) && value.length === 0)) {
      return
    }
    const urls = Array.isArray(value) ? value : [value]
    const nextList: FileItem[] = urls.filter(Boolean).map((v, idx) => ({
      uid: `ext-${idx}-${String(v).slice(-6)}`,
      name: 'image.png',
      url: String(v),
      status: 'done',
    }))
    setFileList(nextList)
  }, [value])

  // 关闭预览
  const handleCancel = useCallback(() => {
    setPreviewVisible(false)
    setPreviewImage('')
  }, [])

  // 预览图片
  const handlePreview = useCallback(async (file: FileItem) => {
    if (!file.url && !file.preview) {
      file.preview = await getBase64(file.originFileObj as File)
    }
    setPreviewImage(file.url || file.preview || '')
    setPreviewVisible(true)
  }, [])

  // 文件大小检查
  const beforeUpload = useCallback(
    (file: File) => {
      const isValidType = accept
        .split(',')
        .some((type) => file.type.includes(type.replace('.', '')))
      if (!isValidType) {
        message.error(`只能上传 ${accept} 格式的图片!`)
        return false
      }

      const isValidSize = file.size / 1024 / 1024 < maxSize
      if (!isValidSize) {
        message.error(`图片大小不能超过 ${maxSize}MB!`)
        return false
      }
      return true
    },
    [accept, maxSize]
  )

  // 上传状态变化处理
  const handleChange = useCallback(
    (info: any) => {
      const { fileList: newFileList, file: currentFile } = info
      // 如果没有文件，清空状态
      if (newFileList.length === 0) {
        setFileList([])
        // 对外抛出空值
        if (onChange) {
          if (maxCount === 1) onChange('')
          else onChange([])
        }
        return
      }

      // 处理上传中状态
      if (currentFile.status === 'uploading') {
        setFileList(newFileList)
        return
      }

      // 删除文件时同步外部值
      if (currentFile.status === 'removed') {
        setFileList(newFileList)
        const urls = newFileList
          .map((f) => f?.url || f?.response?.data?.fileUrl)
          .filter((u): u is string => Boolean(u))
        if (onChange) {
          if (maxCount === 1) onChange(urls[0] || '')
          else onChange(urls)
        }
        return
      }

      // 处理上传完成状态
      if (currentFile.status === 'done') {
        const response = currentFile.response
        if (!response || response.code !== 0) {
          message.error(response?.msg || '上传失败')
          return
        }

        // 更新文件列表，添加URL
        const updatedFileList = newFileList.map((f: FileItem) => ({
          ...f,
          url: f?.response?.data?.fileUrl || f?.url,
        }))
        setFileList(updatedFileList)
        const urls = updatedFileList
          .filter((f) => f && (f.status === 'done' || f.status === 'success'))
          .map((f) => f.url)
          .filter((u): u is string => Boolean(u))
        if (onChange) {
          if (maxCount === 1) onChange(urls[0] || '')
          else onChange(urls)
        }
      }
    },
    [onChange, maxCount]
  )

  // 获取base64用于预览
  const getBase64 = (file: File): Promise<string> => {
    return new Promise((resolve, reject) => {
      const reader = new FileReader()
      reader.readAsDataURL(file)
      reader.onload = () => resolve(reader.result as string)
      reader.onerror = (error) => reject(error)
    })
  }

  // 上传按钮
  const uploadButton = (
    <div
      role="button"
      tabIndex={0}
      aria-label="上传图片"
      style={{
        display: 'flex',
        flexDirection: 'column',
        alignItems: 'center',
        justifyContent: 'center',
        height: '100%',
      }}
    >
      <PlusOutlined style={{ fontSize: '24px', color: '#999' }} />
      <div
        style={{
          marginTop: 8,
          color: '#999',
          fontSize: '14px',
        }}
      >
        <FormattedMessage id="上传" />
      </div>
    </div>
  )

  return (
    <>
      <Upload
        name="image"
        accept={accept}
        action={`${
          apiName === 'platform'
            ? '/api/platform/upload/image'
            : '/api/tenant/upload/image'
        }`}
        headers={{
          'platform-token': getPlatformToken(),
          'tenant-token': getTenantToken(),
        }}
        listType="picture-card"
        fileList={fileList}
        onPreview={handlePreview}
        onChange={handleChange}
        beforeUpload={beforeUpload}
        showUploadList={{
          showPreviewIcon: true,
          showRemoveIcon: true,
          showDownloadIcon: false,
        }}
        maxCount={maxCount}
        data-testid="upload-image"
      >
        {fileList.length >= maxCount ? null : uploadButton}
      </Upload>

      <Modal
        open={previewVisible}
        title="图片预览"
        footer={null}
        onCancel={handleCancel}
        width="auto"
        centered
        data-testid="image-preview-modal"
      >
        <img
          alt="预览图片"
          style={{
            width: '100%',
            maxWidth: '80vw',
            maxHeight: '80vh',
            objectFit: 'contain',
          }}
          src={previewImage}
          onError={() => {
            message.error('图片加载失败')
            handleCancel()
          }}
        />
      </Modal>
    </>
  )
}
